package com.example.java11;

import java.io.FileNotFoundException;
import java.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;

public class TestHttpClient {

    public static void main(String[] args){



    }

    public static HttpClient createHttpClient(){
        // 创建HttpClient实例(构建模式)
        HttpClient httpClient = HttpClient.newBuilder()
                // HTTP协议版本，HTTP2协议的强制要求https，如果⽬标URI是HTTP的，则⽆法使⽤HTTP2协议
                .version(HttpClient.Version.HTTP_2)
                // 设置是否重定向
                .followRedirects(HttpClient.Redirect.NORMAL)
                // 设置链接超时时间
                .connectTimeout(Duration.ofSeconds(30))
                // 设置代理
                .proxy(ProxySelector.of(new InetSocketAddress("192.168.100.202", 8080)))
                // 认证
                .authenticator(Authenticator.getDefault())
                .build();

        // 创建默认的HttpClient实例
        // HttpClient httpClient1 = HttpClient.newHttpClient();

        //创建了HttpClient实例后，可以通过其发送多条请求，不用重复创建。
        return httpClient;
    }

    public static HttpRequest createHttpRequest() throws FileNotFoundException {
        HttpRequest request = HttpRequest.newBuilder()
                // 请求地址
                .uri(URI.create("http://127.0.0.1:8080"))
                // 请求超时时间
                .timeout(Duration.ofSeconds(3))
                // 请求头
                .header("Content-type", "application/json")
                // 请求方式
                .POST(HttpRequest.BodyPublishers.ofFile(Paths.get("data.json")))
                .build();

        return request;
    }

    public static void testGet(){
        HttpClient httpClient = HttpClient.newBuilder()
                .connectTimeout(Duration.ofMillis(3000))
                .build();

        HttpRequest request = HttpRequest.newBuilder().timeout(Duration.ofMillis(3000))
                .uri(URI.create("http://127.0.0.1:8080/data.json")).build();
        try{
            /**
             * send的第二个参数是通过HttpResponse.BodyHandlers的静态工厂来返回一个可以将 response
             * 转换为目标类型T的处理器（handler），本例子中的类型是String。
             * 则使用HttpResponse.BodyHandlers.ofString()
             */
            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            System.out.println(response.body());
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void testPost(){
        HttpClient httpClient = HttpClient.newBuilder()
                .connectTimeout(Duration.ofMillis(3000))
                .build();

        HttpRequest request = HttpRequest.newBuilder().timeout(Duration.ofMillis(3000))
                .uri(URI.create("http://127.0.0.1:8080/data.json"))
                // json数据提交
                //.header("Content-Type", "application/json")
                //.POST(HttpRequest.BodyPublishers.ofString("{\"name\":\"神龟\"}"))
                // 表单提交
                .header("Content-Type", "application/x-www-form-urlencoded")
                // 将java 对象转换为可发送的HTTP request body字节流
                .POST(HttpRequest.BodyPublishers.ofString("name=神龟&age=1000"))
                .build();
        try{
            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            System.out.println(response.body());
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void testAsyn(){
        HttpClient httpClient = HttpClient.newBuilder()
                .connectTimeout(Duration.ofMillis(3000))
                .build();

        HttpRequest request = HttpRequest.newBuilder().timeout(Duration.ofMillis(3000))
                .uri(URI.create("http://127.0.0.1:8080/data.json")).build();
        try{
            /**
             * 异步请求发送之后，会立刻返回 CompletableFuture，
             * 然后可以使用CompletableFuture中的方法来设置异步处理器
             * HttpClient中的send()方法知识sendAsync方法的特例，在send()方法中是先调用sendAsync()方法，
             * 然后直接阻塞等待响应结束再返回
             */
            CompletableFuture<String> result = httpClient
                    .sendAsync(request, HttpResponse.BodyHandlers.ofString())
                    .thenApply(HttpResponse::body);
            System.out.println(result.get());
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}
